package com.corpgovernment.common.supplier;


import com.corpgovernment.common.bo.HttpRetryBo;
import com.corpgovernment.common.bo.HttpRetryInspectBo;
import com.corpgovernment.common.config.CommonApplicationContext;
import com.corpgovernment.common.dataloader.CommonBasicDataloader;
import com.corpgovernment.common.enums.RetryInspectEnum;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

@Slf4j
public class HttpRetryInspect {

    /**
     * 错误编码会出现的名称
     */
    private static final List<String> errorCodeColumnName = Collections.unmodifiableList(Lists.newArrayList("errorCode", "ErrorCode"));

    /**
     * 验签会出现的名称
     */
    private static final List<String> authColumnName = Collections.unmodifiableList(Lists.newArrayList("auth", "Auth"));

    /**
     * ticket名称
     */
    private static final String ticketColumnName = "ticket";

    /**
     * 校验是否需要重试
     * @param rpcResult
     * @return
     */
    public static HttpRetryInspectBo retryInspect(String rpcResult) {
        try {
            if (StringUtils.isBlank(rpcResult)) {
                return HttpRetryInspectBo.success(Boolean.FALSE, null);
            }
            // 获取JSON树形节点
            JsonNode jsonNode = JsonUtils.getJsonNode(rpcResult);
            // 遍历错误码名称
            for (String errorCodeName : errorCodeColumnName) {
                JsonNode errorCodeNode = jsonNode.findValue(errorCodeName);
                if (Objects.nonNull(errorCodeNode) && StringUtils.isNotBlank(errorCodeNode.asText())) {
                    RetryInspectEnum retryInspectEnum = RetryInspectEnum.getByCode(errorCodeNode.asText());
                    if (Objects.nonNull(retryInspectEnum)) {
                        return HttpRetryInspectBo.success(Boolean.TRUE, retryInspectEnum);
                    }
                }
            }
        } catch (Exception ex) {
            log.error("校验是否需要重试异常", ex);
        }
        return HttpRetryInspectBo.success(Boolean.FALSE, null);
    }

    /**
     * 重试处理
     * @return
     */
    public static String retry(HttpRetryBo httpRetryBo, Function<String, String> function) {
        // 1.执行请求
        String httpResult = function.apply(httpRetryBo.getRequestBody());
        // 2.校验请求是否需要重试
        HttpRetryInspectBo httpRetryInspectBo = retryInspect(httpResult);
        // 3.未命中则无需重试
        if (!httpRetryInspectBo.isRetry()) {
            return httpResult;
        }
        // 4.根据异常分配处理方式
        if (RetryInspectEnum.getTicketErrorCodeList().contains(httpRetryInspectBo.getRetryInspectEnum().getCode())) {
            // 处理替换ticket
            String httpRequest = replaceTicket(httpRetryBo);
            if (StringUtils.isNotBlank(httpRequest)) {
                return function.apply(httpRequest);
            }
        }
        return httpResult;
    }


    /**
     * 替换ticket
     * @param httpRetryBo
     * @return
     */
    public static String replaceTicket(HttpRetryBo httpRetryBo) {
        try {
            String supplierTicket = getCommonBasicDataloader().getSupplierTicket(httpRetryBo.getSupplierCorpId(),
                httpRetryBo.getSupplierCode(), Boolean.FALSE);
            if (StringUtils.isNotBlank(supplierTicket)) {
                JsonNode jsonNode = JsonUtils.getJsonNode(httpRetryBo.getRequestBody());
                for (String authName : authColumnName) {
                    JsonNode authNode = jsonNode.get(authName);
                    if (Objects.nonNull(authNode) && StringUtils.isNotBlank(authNode.toString())) {
                        ((ObjectNode)authNode).put(ticketColumnName, supplierTicket);
                        return jsonNode.toString();
                    }
                }
            }
        } catch (Exception ex) {
            log.error("替换ticket异常", ex);
        }
        return null;
    }

    private static CommonBasicDataloader getCommonBasicDataloader(){
        CommonBasicDataloader commonBasicDataloader = CommonApplicationContext.getApplicationContext().getBean("commonBasicDataloader", CommonBasicDataloader.class);
        return commonBasicDataloader;
    }


}
